package tc.de.krawallmann.gravoblocks.game.model;

import java.util.Arrays;

/**
 * A factory for creating Tile objects.
 * 
 * @author KrawallMann
 * @version 1.0
 */
public enum TileShape {

	/** The TYPE I. */
	TYPE_I(new Point[][] {
			{
					new Point(0, 0), new Point(-1, 0), new Point(1, 0), new Point(2, 0)
			}, {
					new Point(0, 0), new Point(0, -1), new Point(0, 1), new Point(0, 2)
			}, {
					new Point(0, 0), new Point(-1, 0), new Point(1, 0), new Point(2, 0)
			}, {
					new Point(0, 0), new Point(0, -1), new Point(0, 1), new Point(0, 2)
			}
	}),

	/** The TYPE J. */
	TYPE_J(new Point[][] {
			{
					new Point(0, 0), new Point(-1, 0), new Point(1, 0), new Point(1, -1)
			}, {
					new Point(0, 0), new Point(0, 1), new Point(0, -1), new Point(-1, -1)
			}, {
					new Point(0, 0), new Point(1, 0), new Point(-1, 0), new Point(-1, 1)
			}, {
					new Point(0, 0), new Point(0, -1), new Point(0, 1), new Point(1, 1)
			}
	}),

	/** The TYPE L. */
	TYPE_L(new Point[][] {
			{
					new Point(0, 0), new Point(1, 0), new Point(-1, 0), new Point(-1, -1)
			}, {
					new Point(0, 0), new Point(0, -1), new Point(0, 1), new Point(-1, 1)
			}, {
					new Point(0, 0), new Point(-1, 0), new Point(1, 0), new Point(1, 1)
			}, {
					new Point(0, 0), new Point(0, 1), new Point(0, -1), new Point(1, -1)
			}
	}),
	
	/** The TYPE U. */
	TYPE_U(new Point[][] {
			{
					new Point(0, 0), new Point(1, 0), new Point(-1, 0), new Point(1, 1), new Point(-1, 1)
			}, {
					new Point(0, 0), new Point(0, -1), new Point(0, 1), new Point(1, 1), new Point(1, -1)
			}, {
					new Point(0, 0), new Point(-1, 0), new Point(1, 0), new Point(1, -1), new Point(-1, -1)
			}, {
					new Point(0, 0), new Point(0, 1), new Point(0, -1), new Point(-1, -1), new Point(-1, 1)
			}
	}),

	/** The TYPE O. */
	TYPE_O(new Point[][] {
			{
					new Point(0, 0), new Point(1, 0), new Point(0, -1), new Point(1, -1)
			}, {
					new Point(0, 0), new Point(1, 0), new Point(0, -1), new Point(1, -1)
			}, {
					new Point(0, 0), new Point(1, 0), new Point(0, -1), new Point(1, -1)
			}, {
					new Point(0, 0), new Point(1, 0), new Point(0, -1), new Point(1, -1)
			}
	}),

	/** The TYPE S. */
	TYPE_S(new Point[][] {
			{
					new Point(0, 0), new Point(1, 0), new Point(0, -1), new Point(-1, -1)
			}, {
					new Point(0, 0), new Point(0, 1), new Point(1, 0), new Point(1, -1)
			}, {
					new Point(0, 0), new Point(1, 0), new Point(0, -1), new Point(-1, -1)
			}, {
					new Point(0, 0), new Point(0, 1), new Point(1, 0), new Point(1, -1)
			}
	}),

	/** The TYPE T. */
	TYPE_T(new Point[][] {
			{
					new Point(0, 0), new Point(-1, 0), new Point(1, 0), new Point(0, -1)
			}, {
					new Point(0, 0), new Point(0, 1), new Point(0, -1), new Point(-1, 0)
			}, {
					new Point(0, 0), new Point(1, 0), new Point(-1, 0), new Point(0, 1)
			}, {
					new Point(0, 0), new Point(0, -1), new Point(0, 1), new Point(1, 0)
			}
	}),
	
	/** The TYPE V. */
	TYPE_V(new Point[][] {
			{
					new Point(0, 0), new Point(-1, 0), new Point(1, 0), new Point(0, -1), new Point(1, 1), new Point(-1, 1)
			}, {
					new Point(0, 0), new Point(0, 1), new Point(0, -1), new Point(-1, 0), new Point(1, 1), new Point(1, -1)
			}, {
					new Point(0, 0), new Point(1, 0), new Point(-1, 0), new Point(0, 1), new Point(-1, -1), new Point(1, -1)
			}, {
					new Point(0, 0), new Point(0, -1), new Point(0, 1), new Point(1, 0), new Point(-1, 1), new Point(-1, -1)
			}
	}),
	
	/** The TYPE PLUS. */
	TYPE_PLUS(new Point[][] {
			{
				new Point(0, 0), new Point(-1, 0), new Point(1, 0), new Point(0, -1), new Point(0, 1)
			}, {
				new Point(0, 0), new Point(-1, 0), new Point(1, 0), new Point(0, -1), new Point(0, 1)
			}, {
				new Point(0, 0), new Point(-1, 0), new Point(1, 0), new Point(0, -1), new Point(0, 1)
			}, {
				new Point(0, 0), new Point(-1, 0), new Point(1, 0), new Point(0, -1), new Point(0, 1)
			}
	}),

	/** The TYPE Z. */
	TYPE_Z(new Point[][] {
			{
					new Point(0, 0), new Point(-1, 0), new Point(0, -1), new Point(1, -1)
			}, {
					new Point(0, 0), new Point(0, 1), new Point(-1, 0), new Point(-1, -1)
			}, {
					new Point(0, 0), new Point(-1, 0), new Point(0, -1), new Point(1, -1)
			}, {
					new Point(0, 0), new Point(0, 1), new Point(-1, 0), new Point(-1, -1)
			}
	});

	/** The positions. */
	private Point[][] positions;

	/**
	 * Instantiates a new tile shape.
	 * 
	 * @param positions
	 *            the positions
	 */
	TileShape(final Point[][] positions) {
		this.positions = Arrays.copyOf(positions, positions.length);
	}

	/**
	 * Gets the length.
	 * 
	 * @return the length
	 */
	public int getLength() {
		return positions.length;
	}

	/**
	 * Gets the positions.
	 * 
	 * @param rotation
	 *            the rotation
	 * @return the positions
	 */
	public Point[] getPositions(final int rotation) {
		return positions[(rotation % positions.length + positions.length) % positions.length];//NOPMD
	}
}
